/*
CTC 协议基础消息结构体定义,根据https://gitee.com/GMSA/CTC文档定义
基础数据报文如下:
数据	长度	意义
包头	2字节	固定0xABCD
P位	1字节	默认从0开始,用于1块主板多个P位,此场景游戏机主板根据此字段判断哪个卡头来的通讯,卡头无需理会此字段,由CTC HUB(协议接线器)来自动处理.
命令标识	2字节	具体功能的标识
事务ID	4字节	用于对通讯过程防重复处理,卡头和游戏机会有发送事务ID和接收事务ID,接收事务ID以0开始,发送事务ID以1开始.游戏机和卡头各自进行保存,每次发送新的指令都把发送事务ID+1进行发送,接收端对比接收事务ID如果和收到的事务ID不相同代表有效,并将自己的接收事务ID等于此ID,如果相同代表已经处理过,回应结果但不处理业务员逻辑,心跳数据无需使用事务ID.如果事务ID超过4字节最大值可再次从1开始.
长度	1字节	数据字段的长度
数据	n字节,n=长度	功能携带的参数
校验	4字节	CRC32国际标准算法,对以上所有数据进行计算(不包含校验字段),算法代码见本仓库源码
*/
#ifndef CCTC_MSG_V1_H
#define CCTC_MSG_V1_H

// 尝试包含标准头文件
#include <stdint.h>

// 如果标准头文件不存在，手动定义常用类型
#ifndef __stdint_h
    // 无符号整数类型
    typedef unsigned          char uint8_t;
    typedef unsigned short     int uint16_t;
    typedef unsigned           int uint32_t;
    typedef unsigned       __INT64 uint64_t;

    // 有符号整数类型
    typedef   signed          char int8_t;
    typedef   signed short     int int16_t;
    typedef   signed           int int32_t;
    typedef   signed       __INT64 int64_t;
#endif

/**
 * @brief CTC协议常量定义
 */
#define CTC_HEADER         0xABCD // 帧头标识
#define CTC_MAX_DATA_LEN   242    // 最大数据长度
#define CTC_FRAME_OVERHEAD 14     // 帧头+校验等固定长度
#define CTC_MIN_FRAME_TIME 10     // 最小帧间隔时间,单位毫秒
#define CTC_BUSYRETRY_TIME 200     // 对方设备忙时重试间隔,单位毫秒
#define CTC_RESEND_TIMEOUT 400     // 没有收到ACK重发超时时间,单位毫秒
#define CTC_MAX_FRAME_LEN  256    // 最大帧长
#define CTC_DEFAULT_PORTID 0      // 默认P位
#define CTC_RECEIVE_TIMEOUT 100   // 接收超时时间,单位毫秒
#define CTC_MAXRESEND_TIMES  3     // 最大重发次数
#define CTC_WAITTIMEONERR 1000   // 通讯错误时等待时间,单位毫秒
#define CTC_HEARTBEAT_TIME 10000   // 心跳间隔时间,单位毫秒
#define CTC_OFFLINE_TIME 25000   // 心跳间隔时间,单位毫秒
#define CTC_HANDSHAKE_RETRY_TIME  5000 // 握手重试间隔,单位毫秒
#define CTC_ACKFRAME_LEN  17 // ACK帧长度

/**
 * @brief CTC命令标识枚举
 */
#define CTC_CMD_ACK             0x0001 // 应答指令
#define CTC_CMD_HANDSHAKE       0x0002 // 握手指令
#define CTC_CMD_HANDSHAKE_RSP   0x0003 // 握手应答
#define CTC_CMD_METER_READ      0x0004 // 抄表指令
#define CTC_CMD_METER_DATA      0x0005 // 抄表数据回传
#define CTC_CMD_HEARTBEAT       0x0006 // 心跳指令
#define CTC_CMD_HEARTBEAT_RSP   0x0007 // 心跳应答
#define CTC_CMD_COIN_IN         0x0008 // 投币指令
#define CTC_CMD_COIN_IN_RSP     0x0009 // 投币应答
#define CTC_CMD_CHANNEL_SEL     0x000A // 通道选择指令
#define CTC_CMD_REWARD          0x000B // 奖励指令
#define CTC_CMD_PHYSICAL_REPORT 0x000C // 实体上报指令
#define CTC_CMD_QUERY_COIN      0x000D // 查询投币数
#define CTC_CMD_QUERY_COIN_RSP  0x000E // 查询投币数应答
#define CTC_CMD_SET_COIN        0x000F // 设置投币数
#define CTC_CMD_ATMOSPHEREEVENT 0x0010 // 氛围控制指令

/**
 * @brief CTC命令数据长度枚举
 */
#define CTC_CMDLEN_ACK             3   // 2 + 1（ACK消息长度）
#define CTC_CMDLEN_HANDSHAKE       22  // 4 + 16 + 2（CTC_HandshakeMsgV1）
#define CTC_CMDLEN_HANDSHAKE_RSP   22  // 4 + 16 + 2（CTC_HandshakeRspMsgV1）
#define CTC_CMDLEN_METER_DATA_RSP  50   // 1 + 4（CTC_MeterDataRspMsgV1）
#define CTC_CMDLEN_HEARTBEAT       1   // 1（CTC_HeartbeatMsgV1）
#define CTC_CMDLEN_HEARTBEAT_RSP   3   // 1 + 2（CTC_HeartbeatRspMsgV1）
#define CTC_CMDLEN_COIN_IN         36  // 4 + 16 + 16（CTC_CoinInMsgV1）
#define CTC_CMDLEN_COIN_IN_RSP     17  // 1 + 16（CTC_CoinInRspMsgV1）
#define CTC_CMDLEN_CHANNEL_SEL     2   // 1 + 1（CTC_ChannelSelMsgV1）
#define CTC_CMDLEN_REWARD          5   // 1 + 4（CTC_RewardMsgV1）
#define CTC_CMDLEN_PHYSICAL_REPORT 5   // 1 + 4（CTC_PhysicalReportMsgV1）
#define CTC_CMDLEN_QUERY_COIN      2   // 2（CTC_CoinPriceMsgV1）
#define CTC_CMDLEN_SET_COIN        2   // 2（CTC_CoinPriceMsgV1）
#define CTC_CMDLEN_ATMOSPHERE_EVENT 7  // 2 + 1 + 4（CTC_AtmosphereData）

/**
 * @brief ACK结果码(CTC_CMD_ACK)
 * @note 0x00表示成功,其他值表示错误,如果是设备忙需要稍后重试
 * @note 错误码定义参考CTC协议文档
 */
typedef enum {
    CTC_ACK_SUCCESS     = 0x00, // 成功
    CTC_ACK_HEADER_ERR  = 0x01, // 包头错误
    CTC_ACK_CRC_ERR     = 0x02, // CRC错误
    CTC_ACK_LENGTH_ERR  = 0x03, // 长度错误
    CTC_ACK_UNSUPPORTED = 0x04, // 不支持的命令
    CTC_ACK_TIMEOUT     = 0x05, // 超时
    CTC_ACK_BUSY        = 100   // 设备忙,接收方缓冲区已满
} CTC_AckResult;

/**
 * @brief CTC握手消息结构体(CTC_CMD_HANDSHAKE)
 * @note 用于设备与服务器之间的握手,确认设备信息和支持的CTC协议版本
 * @note 握手成功后,服务器会返回CTC_CMD_HANDSHAKE_RSP消息
 * @note Master端需要兼容各版本CTC协议,Slave端只需支持某个版本,握手由Master端发起
 */
typedef struct {
    uint32_t ProductID;     // 产品ID
    uint8_t DeviceID[16];   // 设备ID,需要保证全球唯一
    uint16_t MaxCTCVersion; // 支持的CTC协议最高版本
} CTC_HandshakeMsgV1;

/**
 * @brief CTC握手应答消息结构体(CTC_CMD_HANDSHAKE_RSP)
 * @note 握手应答消息由Master端发起,Slave端回应
 */
typedef struct {
    uint32_t ProductID;     // 产品ID
    uint8_t DeviceID[16];   // 设备ID,需要保证全球唯一
    uint16_t MaxCTCVersion; // 支持的CTC协议最高版本
} CTC_HandshakeRspMsgV1;


#define CTC_METER_TYPE_COIN_IN_TOTAL         0   // 投币总数
#define CTC_METER_TYPE_ELECTRONIC_COIN_TOTAL 1   // 电子币总数
#define CTC_METER_TYPE_PHYSICAL_COIN_TOTAL   2   // 实物币
#define CTC_METER_TYPE_TICKET_TOTAL          10  // 出票总数
#define CTC_METER_TYPE_ELECTRONIC_TICKET_TOTAL 11 // 出电子票总数
#define CTC_METER_TYPE_PHYSICAL_TICKET_TOTAL 12  // 出实物票
#define CTC_METER_TYPE_BLUE_TICKET_TOTAL     20  // 出蓝票总数
#define CTC_METER_TYPE_CARD_TOTAL     30  // 出卡片总数
#define CTC_METER_TYPE_ELECTRONIC_BLUE_TICKET_TOTAL 21 // 出电子蓝票总数
#define CTC_METER_TYPE_PHYSICAL_BLUE_TICKET_TOTAL 22 // 出实物蓝票总数
#define CTC_METER_TYPE_PHYSICAL_REWARD1_TOTAL 100 // 出实物礼品1总数
#define CTC_METER_TYPE_PHYSICAL_REWARD2_TOTAL 101 // 出实物礼品2总数
#define CTC_METER_TYPE_PHYSICAL_REWARD3_TOTAL 102 // 出实物礼品3总数
#define CTC_METER_TYPE_PHYSICAL_REWARD4_TOTAL 103 // 出实物礼品4总数
#define CTC_METER_TYPE_PHYSICAL_REWARD5_TOTAL 104 // 出实物礼品5总数
#define CTC_METER_TYPE_END 255 // 数据结束

/// @brief CTC抄表数据项结构体
typedef struct {
    uint8_t MeterType;   // 码表类型0=投币总数,1=电子币总数,2=实物币总数,10=出票总数,11=出电子票总数,12=出实物票总数,20=出蓝票总数,21=出电子蓝票总数,22=出实物蓝票总数,30=总出卡片数,100=出礼品1总数,101=出实物礼品2总数,102=出实物礼品2总数,103=出实物礼品4总数,104=出实物礼品5总数,...130=出实物礼品31总数,255=无效数据(无效后面不能再放有效数据)
    uint32_t MeterValue; // 抄表数据
} CTC_MeterDataItemV1;

/**
 * @brief CTC抄表回应消息结构体(CTC_CMD_METER_DATA)
 */
typedef struct {
    CTC_MeterDataItemV1 Items[10]; // 最多10项抄表数据
} CTC_MeterDataRspMsgV1;


///Master状态
#define CTC_MASTER_STATE_IDLE        0   // 正常状态
#define CTC_MASTER_STATE_WAITCONFIG  1   // 等待配置
#define CTC_MASTER_STATE_SERVERERROR  2   // 门店管理系统错误
#define CTC_MASTER_STATE_CONNECTERROR   3   // 链接错误
#define CTC_MASTER_STATE_DISCONNECTTING 4  // 正在联网

/**
 * @brief 心跳指令数据结构 (CTC_CMD_HEARTBEAT)
 */
typedef struct {
    uint8_t Status; // 设备状态：0=正常可用,1=等待配网,2=连接门店服务异常,3=网络无法连接,4=正在联网
} CTC_HeartbeatMsgV1;

/**
 * @brief 心跳应答数据结构 (CTC_CMD_HEARTBEAT_RSP)
 */
typedef struct {
    uint8_t AllowCoin; // 允许投币：0=卡头可正常消费,1=卡头不可进行消费
    uint16_t Status;   // 错误码（小端）：0=无故障,非0=有故障,会将错误码上报给服务器
} CTC_HeartbeatRspMsgV1;

/**
 * @brief 投币指令数据结构 (CTC_CMD_COIN_IN)
 */
typedef struct {
    uint32_t CoinCount;   // 投币数量
    uint8_t MemberId[16]; // 会员ID
    uint8_t RecordId[16]; // 消费记录ID
} CTC_CoinInMsgV1;

/**
 * @brief 投币应答数据结构 (CTC_CMD_COIN_IN_RSP)
 */
typedef struct {
    uint8_t Result;       // 处理结果：0=成功，1=失败,失败时会回退会员消费,请慎重使用
    uint8_t RecordId[16]; // 消费记录ID（回传投币时给的消费记录ID）
} CTC_CoinInRspMsgV1;

/**
 * @brief 通道选择指令数据结构 (CTC_CMD_CHANNEL_SEL)
 */
typedef struct {
    uint8_t Ticket;     // 彩票通道,0=实物,1=电子,2=暂时不出票
    uint8_t BlueTicket; // 蓝票通道,0=实物,1=电子,2=暂时不出票
} CTC_ChannelSelMsgV1;


#define CTC_REWARD_TYPE_TICKET      0   // 奖励彩票
#define CTC_REWARD_TYPE_BLUETICKET        1   // 奖励蓝票
#define CTC_REWARD_TYPE_SCORE   10  // 游戏任务得分

/**
 * @brief 奖励指令数据结构 (CTC_CMD_REWARD)
 */
typedef struct {
    uint8_t RewardType;   // 奖励类型0=奖励彩票,1=奖励蓝票,10=游戏任务得分
    uint32_t RewardCount; // 奖励数量
} CTC_RewardMsgV1;

//实物奖励定义
#define CTC_PHYSICAL_REWARD_TYPE_REALCOIN   0   // 实物币
#define CTC_PHYSICAL_REWARD_TYPE_REALTICKET 1  // 实物彩票
#define CTC_PHYSICAL_REWARD_TYPE_REALBLUETICKET   2  // 实物蓝票
#define CTC_PHYSICAL_REWARD_TYPE_CRAD   3  // 实物卡片
#define CTC_PHYSICAL_REWARD_TYPE_GIFT1      100 // 实物礼品1
#define CTC_PHYSICAL_REWARD_TYPE_GIFT2      101 // 实物礼品2
#define CTC_PHYSICAL_REWARD_TYPE_GIFT3      102 // 实物礼品3

/**
 * @brief 实体上报指令数据结构 (CTC_CMD_PHYSICAL_REPORT)
 */
typedef struct {
    uint8_t PhysicalType;   // 实体类型0=实物币,1=实物彩票,2=实体蓝票,3=实物卡片,100=实物礼品1,101=实物礼品2...130=实物礼品31
    uint32_t PhysicalCount; // 实体数量
} CTC_PhysicalReportMsgV1;

/**
 * @brief 查询投币数指令数据（CTC_CMD_QUERY_COIN）
 * 说明：查询指定类型的投币总数
 */
typedef struct {
    uint16_t CoinPerGame; // 每局币数
} CTC_CoinPriceMsgV1;

//氛围等级
#define CTC_ATMOSPHERE_LEVEL_SMALL 100  //小事件,一般100彩票左右
#define CTC_ATMOSPHERE_LEVEL_MEDIUM 200 //中事件,一般500彩票左右
#define CTC_ATMOSPHERE_LEVEL_LARGE 300 //大事件,一般1000彩票左右
#define CTC_ATMOSPHERE_LEVEL_SUPER 400 //超大事件,一般5000彩票左右
#define CTC_ATMOSPHERE_LEVEL_ULTRA 500 //终极事件

//氛围奖励
#define CTC_ATMOSPHERE_REWARD_TICKET      0   // 奖励彩票
#define CTC_ATMOSPHERE_REWARD_BLUETICKET        1   // 奖励蓝票
#define CTC_ATMOSPHERE_REWARD_SCORE   10  // 游戏任务得分
#define CTC_ATMOSPHERE_REWARD_GIFT   100 // 奖励实物
/**
 * @brief 氛围控制指令数据（CTC_CMD_ATMOSPHEREEVENT）
 * 说明：控制设备灯光/声音等氛围
 */
typedef struct {
    uint16_t EventLevel;  // 事件等级
    uint8_t RewardType;   // 此事件将要奖励类型0=奖励彩票,1=奖励蓝票,10=游戏任务得分,100=奖励实物
    uint32_t RewardCount; // 此事件将要奖励数量
} CTC_AtmosphereDataV1;

#endif

